﻿Imports System.ComponentModel
Imports System.IO
Imports System.Net.FtpClient
Imports SFDL.Core
Imports BrightIdeasSoftware
Imports System.Threading
Imports System.Text
Imports System.Threading.Tasks
Imports Microsoft.WindowsAPICodePack.Taskbar
Imports SFDL.LoaderExtensions
Imports SFDL.Logging
Imports SFDL.Loader.My.Resources
Imports System.Text.RegularExpressions

Public Class frm_main

    Private _obj_lock_Task As New Object
    Private _obj_lock_init As New Object

    Private _tools As New Tools

    Private _taskbar_manager As TaskbarManager
    Private _thread_handler As New ThreadHandler

    Private _post_dl_exit_app As Boolean = False
    Private _post_dl_shutdown_computer As Boolean = False

    Private _block_app_exit As Boolean = False
    Private _unrar_active As Boolean = False

    Private Shared _log As NLog.Logger = NLog.LogManager.GetLogger("Main")
    Private Shared _log_unrar As NLog.Logger = NLog.LogManager.GetLogger("UnRAR")

#Region "Private/Friend ReadOnly Properties"

    Protected ReadOnly Property PostDownloadExitApp As Boolean
        Get
            Return _post_dl_exit_app
        End Get
    End Property

    Protected ReadOnly Property PostDownloadShutdownComputer As Boolean
        Get
            Return _post_dl_shutdown_computer
        End Get
    End Property

    Protected Friend ReadOnly Property GetTaskbarManager As TaskbarManager
        Get
            Return _taskbar_manager
        End Get
    End Property

#End Region

#Region "Event Handler"

    Private Sub frm_setting_settings_update_event(ByVal sender As Object, e As SettingsUpatedEventArgs)
        _settings = e.NewSettings

        Task.Run(Sub()
                     ProgressRemoteControlState(_settings.RemoteControlSettings)
                 End Sub)

    End Sub

    Private Sub StopDownloadCompleteEvent(ByVal sender As Object, ByVal e As EventArgs)

        Try

            If Me.InvokeRequired Then
                Me.Invoke(Sub() Me.StopDownloadCompleteEvent(sender, New EventArgs))
            Else

                tbl_stop_download.Enabled = False
                tbl_start_download.Enabled = True
                _var_download_running = False

                tss_currentspeed.Text = String.Empty
                tss_time_remaining.Text = String.Empty
                tss_progressbar.Value = 0

                tss_status.Text = StringMessages.StopDownloadCompleteEventStatusMessage

            End If

        Catch ex As Exception

        End Try

    End Sub

    Private Sub FileDownloadCompleteEvent(ByVal sender As Object, ByVal e As FileDownloadCompleteEventArg)

        Dim _enabled As Boolean = False


        Task.Run(Sub()

                     If isSessionComplete(GetSFDLSessionByKey(e.OLVItem.SFDLSessionName)) = True Then

                         Dim _sfdl_session As SFDLSession = GetSFDLSessionByKey(e.OLVItem.SFDLSessionName)

                         If _settings.SpeedReportSettings.SpeedreportView = SpeedreportView.ShowGUI Or _settings.SpeedReportSettings.SpeedreportView = SpeedreportView.Write2File Then

                             Dim _speedreport As String
                             Dim _speedreporttask As Guid

                             _speedreporttask = AddTask(StringMessages.SpeedreportTaskCreate)

                             _speedreport = GenerateSpeedreport(_sfdl_session)

                             If Not String.IsNullOrEmpty(_speedreport) Then

                                 SetTaskComplete(_speedreporttask, StringMessages.SpeedreportTaskCompleted)

                                 If (_settings.SpeedReportSettings.SpeedreportView = SpeedreportView.ShowGUI And _post_dl_exit_app = False) And _post_dl_shutdown_computer = False Then

                                     frm_speedreport.SpeedReportText = _speedreport
                                     frm_speedreport.ShowDialog()
                                     frm_speedreport.Dispose()

                                 Else

                                     Dim _path As String

                                     _path = GetDownloadFilePath(GetSettings, _sfdl_session, _sfdl_session.OLVItemList(0))

                                     _path = _path.Replace(_sfdl_session.OLVItemList(0).FileName, "")
                                     _path = IO.Path.Combine(_path, "Speedreport.txt")

                                     My.Computer.FileSystem.WriteAllText(_path, _speedreport, False, System.Text.Encoding.Default)

                                 End If


                             Else
                                 SetTaskComplete(_speedreporttask, StringMessages.SpeedreportTaskFailed, True)
                             End If

                         End If

                     End If

                 End Sub)


        Task.Run(Sub()

                     _log.Debug("Prüfe ob etwas entpackt werden kann....")

                     _log.Debug("{0} UnRAR Chains gefunden", (GetSFDLSessionByKey(e.OLVItem.SFDLSessionName)).UnRarChains.Count)

                     'Prüfen ob die Chain schon komplett ist und daher alles schon entackt werden kann
                     For Each _chain In (GetSFDLSessionByKey(e.OLVItem.SFDLSessionName)).UnRarChains

                         If isUnRarChainComplete(_chain) = True Then

                             _log.Debug("Chain {0} ist komplett!", _chain.MasterUnRarChainFile.FileName.ToString)

                             If _settings.UnRARSettings.UnRARAfterDownload = True And _chain.UnRARDone = False Then
                                 _block_app_exit = True
                                 _unrar_active = True
                                 UnRAR(AddTask(StringMessages.UnRARExtractingFilesTaskStartMessage), _chain, e.OLVItem.SFDLSessionName)
                             Else
                                 _block_app_exit = False
                                 _unrar_active = False
                             End If


                         Else 'Entpacken noch nicht möglich -> Prüfen ob InstantVideo möglich ist

                             _log.Debug("Chain {0} ist NICHT komplett!", _chain.MasterUnRarChainFile.FileName.ToString)

                             If _settings.InstantVideo = True And IsReadyForInstantVideo(_chain) = True Then
                                 _enabled = True
                             End If

                         End If

                     Next

                 End Sub).ContinueWith(Sub()
                                           cmd_instantvideo.Enabled = _enabled
                                       End Sub, New CancellationToken, TaskContinuationOptions.None, GetRootUIContext)



    End Sub


    Private Sub DownloadCompleteEvent(ByVal sender As Object, ByVal e As EventArgs)

        Task.Run(Sub()

                     Try

                         Dim _task As Task(Of CheckIfDownloadCompleteResult)

                         _task = Task.Run(Function()

                                              Return CheckIfDownloadComplete()

                                          End Function)

                         If _task.Result.AllSessionsComplete = True Then

                             RemoveHandler ThreadHandler.DownloadCompleted, AddressOf DownloadCompleteEvent

                             Task.Factory.StartNew(Sub()

                                                       tbl_stop_download.Enabled = False
                                                       tbl_start_download.Enabled = True
                                                       _var_download_running = False

                                                       tss_currentspeed.Text = String.Empty
                                                       tss_time_remaining.Text = String.Empty
                                                       tss_progressbar.Value = 0

                                                       tss_status.Text = StringMessages.DownloadCompleteStatusMessage
                                                       tss_status.Image = My.Resources.tick

                                                   End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext).ContinueWith(Sub()

                                                                                                                                                While _block_app_exit = True
                                                                                                                                                    'Wait
                                                                                                                                                    System.Threading.Thread.Sleep(5000)
                                                                                                                                                End While

                                                                                                                                                If _post_dl_shutdown_computer = True Then
                                                                                                                                                    PostDLAction_ShutdownComputer()

                                                                                                                                                Else

                                                                                                                                                    'Müssen wir nur machen wenn der PC nicht heruntergefahren wird

                                                                                                                                                    If _post_dl_exit_app = True Then
                                                                                                                                                        PostDLAction_ExitApp()
                                                                                                                                                    End If

                                                                                                                                                End If

                                                                                                                                            End Sub)


                             If TaskbarManager.IsPlatformSupported Then
                                 _taskbar_manager.SetProgressState(TaskbarProgressBarState.NoProgress)
                                 _taskbar_manager.SetProgressValue(0, 100)
                             End If

                         End If

                     Catch ex As Exception

                     End Try

                 End Sub)

    End Sub

#End Region

#Region "ObjectListView Events & Funktionen"

    Private Sub OLV_Download_Items_GroupTaskClicked(sender As Object, e As GroupTaskClickedEventArgs) Handles OLV_Download_Items.GroupTaskClicked

        Dim _group_move_direction As GroupMoveDirection

        frm_groupmover.ShowDialog()
        _group_move_direction = frm_groupmover.GetGroupMoveDirection
        frm_groupmover.Dispose()

        Monitor.Enter(_obj_lock_SFDLSessionList)

        Task.Run(Sub()

                     Dim _old_session_index As Integer
                     Dim _reorder_sfdl_session As SFDLSession = Nothing

                     Try

                         For Each _item In GetSFDLSessionByKey(e.Group.Name).OLVItemList

                             _old_session_index = CInt(_item.GroupSortIndicator.Split(CChar(";"))(0))

                             Select Case _group_move_direction

                                 Case GroupMoveDirection.GroupMoveUp

                                     If _old_session_index = 1 Then
                                         Throw New InvalidGroupMoveException
                                     End If

                                     _item.GroupSortIndicator = String.Format("{0};{1};{2}", _old_session_index - 1, _item.PackageName, _item.SFDLSessionName)

                                 Case GroupMoveDirection.GroupMoveDown

                                     If _old_session_index = GetSFDLSessionList.Count Then
                                         Throw New InvalidGroupMoveException
                                     End If

                                     _item.GroupSortIndicator = String.Format("{0};{1};{2}", _old_session_index + 1, _item.PackageName, _item.SFDLSessionName)

                                 Case GroupMoveDirection.GroupMoveMostTop

                                     If _old_session_index = 1 Then
                                         Throw New InvalidGroupMoveException
                                     End If

                                     _item.GroupSortIndicator = String.Format("{0};{1};{2}", 1, _item.PackageName, _item.SFDLSessionName)

                                 Case GroupMoveDirection.GroupMoveMostDown

                                     If _old_session_index = GetSFDLSessionList.Count Then
                                         Throw New InvalidGroupMoveException
                                     End If

                                     _item.GroupSortIndicator = String.Format("{0};{1};{2}", GetSFDLSessionList.Count, _item.PackageName, _item.SFDLSessionName)

                             End Select

                         Next

                         Select Case _group_move_direction

                             Case GroupMoveDirection.GroupMoveUp

                                 _reorder_sfdl_session = _var_sfdl_session_list.ElementAt(_old_session_index - 2).Value

                             Case GroupMoveDirection.GroupMoveDown

                                 _reorder_sfdl_session = _var_sfdl_session_list.ElementAt(_old_session_index).Value

                         End Select

                         If Not _reorder_sfdl_session Is Nothing Then

                             For Each _item In _reorder_sfdl_session.OLVItemList
                                 _item.GroupSortIndicator = String.Format("{0};{1};{2}", _old_session_index, _item.PackageName, _item.SFDLSessionName)
                             Next

                         End If

                         Task.Factory.StartNew(Sub()

                                                   OLV_Download_Items.ClearObjects()

                                                   For Each _session_obj In _var_sfdl_session_list
                                                       OLV_Download_Items.AddObjects(_session_obj.Value.OLVItemList)
                                                   Next

                                                   OLV_Download_Items.BuildGroups(olvc_groupsort, SortOrder.None)

                                               End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext).ContinueWith(Sub()

                                                                                                                                            SyncSFDLSessionwithGUI()

                                                                                                                                        End Sub)

                     Catch ex As Exception
                         _log.Error(ex, ex.Message)
                     End Try

                 End Sub)

        Monitor.Exit(_obj_lock_SFDLSessionList)

    End Sub


    Private Sub AllePaketeToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AllePaketeToolStripMenuItem.Click

        Task.Factory.StartNew(Sub()

                                  For Each _group In OLV_Download_Items.OLVGroups

                                      Dim _sfdl_session_id As String = String.Empty

                                      _group.Collapsed = True

                                      If Not String.IsNullOrEmpty(_group.Key.ToString) And _group.Key.ToString.Contains(";") Then
                                          _sfdl_session_id = _group.Key.ToString.Split(CChar(";"))(2).ToString
                                      End If

                                      SetSFDLSessionGroupState(_sfdl_session_id, SFDLSessionEnums.GroupState.Collapsed)

                                  Next

                              End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext)

    End Sub

    Private Sub AllePaketeToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles AllePaketeToolStripMenuItem1.Click

        Task.Factory.StartNew(Sub()

                                  For Each _group In OLV_Download_Items.OLVGroups

                                      Dim _sfdl_session_id As String = String.Empty

                                      _group.Collapsed = False

                                      If Not String.IsNullOrEmpty(_group.Key.ToString) And _group.Key.ToString.Contains(";") Then
                                          _sfdl_session_id = _group.Key.ToString.Split(CChar(";"))(2).ToString
                                      End If

                                      SetSFDLSessionGroupState(_sfdl_session_id, SFDLSessionEnums.GroupState.Expanded)

                                  Next

                              End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext)

    End Sub

    Private Sub OLV_Download_Items_GroupExpandingCollapsing(sender As Object, e As GroupExpandingCollapsingEventArgs) Handles OLV_Download_Items.GroupExpandingCollapsing

        Dim _sfdl_session_id As String = String.Empty

        Try

            If Not String.IsNullOrEmpty(e.Group.Key.ToString) And e.Group.Key.ToString.Contains(";") Then
                _sfdl_session_id = e.Group.Key.ToString.Split(CChar(";"))(2).ToString
            End If

            If e.Group.Collapsed = True Then
                SetSFDLSessionGroupState(_sfdl_session_id, SFDLSessionEnums.GroupState.Collapsed)
            Else
                SetSFDLSessionGroupState(_sfdl_session_id, SFDLSessionEnums.GroupState.Expanded)
            End If

        Catch ex As Exception
            _log.Error("GroupState konnte nicht gespeichert werden!")
        End Try

    End Sub

    Private Sub OLV_Download_Items_AboutToCreateGroups(sender As Object, e As CreateGroupsEventArgs) Handles OLV_Download_Items.AboutToCreateGroups

        Dim _procressed_sessions As New List(Of String)

        Parallel.ForEach(e.Groups, Sub(_group As OLVGroup)

                                       Dim _sfdl_session_id As String = String.Empty
                                       Dim _packagename As String = String.Empty
                                       Dim _sfdl_session As SFDLSession

                                       If Not String.IsNullOrEmpty(_group.Key.ToString) And _group.Key.ToString.Contains(";") Then
                                           _sfdl_session_id = _group.Key.ToString.Split(CChar(";"))(2).ToString
                                           _packagename = _group.Key.ToString.Split(CChar(";"))(1).ToString
                                       End If

                                       _sfdl_session = GetSFDLSessionByKey(_sfdl_session_id)

                                       If Not _sfdl_session.SFDLFile.ConnectionInfo.EncryptionMode = FtpEncryptionMode.None Then
                                           _group.TitleImage = 1 'SSL LOgo
                                       End If

                                       _group.Header = String.Format("{0} | {1}", _sfdl_session.SFDLFile.Description, _packagename)
                                       _group.Tag = _packagename.ToString
                                       _group.Name = _sfdl_session_id
                                       _group.Subtitle = String.Format("Uploader: {0}", _sfdl_session.SFDLFile.Uploader)

                                       If Not _procressed_sessions.Contains(_sfdl_session_id) Then
                                           _group.Task = StringMessages.GroupTaskChangePriority
                                       End If

                                       If _sfdl_session.GroupState = SFDLSessionEnums.GroupState.Collapsed Then
                                           _group.Collapsed = True
                                       Else
                                           _group.Collapsed = False
                                       End If

                                       _procressed_sessions.Add(_sfdl_session_id)

                                   End Sub)

    End Sub

    Private Shared Function ImageUpdateEventImageGetter(ByVal _row_object As Object) As Object

        Dim _olv_item As New OLV_Item

        Dim _rt As New Object

        Try

            _olv_item = DirectCast(_row_object, OLV_Item)

            If _olv_item.StopMarkSet = True Then
                _rt = 13
            End If

            Select Case _olv_item.Status

                Case Status.AlreadyDownloaded

                    _rt = 6

                Case Status.Complete

                    _rt = 6

                Case Status.CompleteHashValid

                    _rt = 10

                Case Status.CompleteHashInvalid

                    _rt = 11

                Case Status.FileValdilation

                    _rt = 0

                Case Status.Failure

                    _rt = 5

                Case Status.Waiting

                    _rt = 7

                Case Status.Stopped

                    _rt = 8

                Case Status.Running

                    _rt = 9

                Case Status.Retry

                    _rt = 12

                Case Else

                    _rt = Nothing

            End Select

        Catch ex As Exception

        End Try

        Return _rt

    End Function

    Private Sub OLV_Download_Items_ItemChecked(sender As Object, e As ItemCheckedEventArgs) Handles OLV_Download_Items.ItemChecked

        Try

            Monitor.Enter(_obj_lock_SFDLSessionList)

            If GetDownloadRunning Then

                Dim _olv_item As OLV_Item

                _olv_item = CType(OLV_Download_Items.GetModelObject(e.Item.Index), OLV_Item)

                Select Case _olv_item.Checked

                    Case True

                        _olv_item.Status = Status.Waiting
                        _olv_item.StatusText = "Warte..."
                        OLV_Download_Items.CheckObject(_olv_item)

                        _thread_handler.CheckForNewThreads()

                    Case False

                        _olv_item.Status = Status.Queued
                        _olv_item.StatusText = String.Empty
                        OLV_Download_Items.UncheckObject(_olv_item)

                End Select

            End If

        Catch ex As Exception
            _log.Error(ex, ex.Message)
        Finally
            Monitor.Exit(_obj_lock_SFDLSessionList)
        End Try

    End Sub

    Private Sub OLV_Download_Items_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles OLV_Download_Items.ItemCheck

        If GetDownloadRunning Then

            Try

                Dim _olv_item As OLV_Item

                _olv_item = CType(OLV_Download_Items.GetModelObject(e.Index), OLV_Item)

                Select Case e.NewValue

                    Case CheckState.Unchecked

                        Select Case _olv_item.Status

                            Case Status.Retry 'Änderung verbieten

                                e.NewValue = e.CurrentValue

                            Case Status.Running 'Änderung verbieten

                                e.NewValue = e.CurrentValue

                            Case Status.FileValdilation 'Änderung verbieten

                                e.NewValue = e.CurrentValue

                        End Select

                End Select

            Catch ex As Exception
                _log.Error(ex, ex.Message)
            End Try

        End If

    End Sub

#End Region

#Region "Open SFDL Funktionen"

    Protected Friend Sub OpenSFDLHelper(ByVal _file_list As String(), Optional ByVal _session_restore As Boolean = False, Optional ByVal _init As Boolean = False)

        Dim _index_task_session_restore As Guid
        Dim _index_task_open_file As Guid
        Dim _tasklist As New List(Of Guid)

        If (Me.WindowState = FormWindowState.Minimized And _init = False) Or (NotifyIcon.Visible = True And Me.WindowState = FormWindowState.Minimized) Then 'Fenster wieder maximieren wenn es im Tray ist

            OLV_Download_Items.Visible = True
            Me.Show()
            Me.WindowState = FormWindowState.Normal
            NotifyIcon.Visible = False

        End If

        If _session_restore = True Then

            _index_task_open_file = AddTask(StringMessages.OpenSFDLFilesTaskStartMessage)
            _index_task_session_restore = AddTask(StringMessages.OpenSFDLSessionsTaskStartMessage)

            _tasklist.Add(_index_task_open_file)
            _tasklist.Add(_index_task_session_restore)

            OpenSFDLSessions(Directory.GetFiles(Path.Combine(Environment.GetEnvironmentVariable("appdata"), "SFDL.NET 2"), "*.restore", SearchOption.TopDirectoryOnly), _index_task_session_restore)

            OpenSFDLFiles(_file_list.ToArray, _index_task_open_file)

            PostOpenSFDL(_tasklist)

        Else

            _index_task_open_file = AddTask(StringMessages.OpenSFDLFilesTaskStartMessage)
            _tasklist.Add(_index_task_open_file)

            OpenSFDLFiles(_file_list.ToArray, _index_task_open_file)

            If _settings.DeleteSFDLAfterOpen = True Then
                For Each _file In _file_list
                    If IO.File.Exists(_file) Then
                        IO.File.Delete(_file)
                    End If
                Next
            End If

            PostOpenSFDL(_tasklist)

        End If

    End Sub

    Friend Sub PostOpenSFDL(_taskidlist As List(Of Guid))

        For Each _restore_file In Directory.GetFiles(Path.Combine(Environment.GetEnvironmentVariable("appdata"), "SFDL.NET 2"), "*.restore", SearchOption.TopDirectoryOnly)
            Try
                IO.File.Delete(_restore_file)
            Catch ex As Exception
                _log.Error(ex, "Fehler im Restore File - Datei konnte nicht wiederhergestellt werden")
            End Try
        Next


        For Each _id In _taskidlist
            SetTaskComplete(_id, StringMessages.GeneralTaskCompleteMessage)
        Next

        ParseUnRARChains()

        SyncSFDLSessionwithGUI()

        RefreshCustomCommandPlugin(_plugin_connector)

    End Sub

#End Region

#Region "UnRAR"
    Friend Function ParseUnRARArchiveFiles(ByVal _line As String) As String

        Dim _archive_file As String = String.Empty
        Dim sourcestring As String = _line

        If Not _line.StartsWith("Extracting from") Then

            Dim re As Regex = New Regex("^Extracting[ ]{1,2}.{1,255}\..{1,3}")
            Dim mc As MatchCollection = re.Matches(sourcestring)
            Dim mIdx As Integer = 0

            For Each m As Match In mc
                For groupIdx As Integer = 0 To m.Groups.Count - 1
                    If Not String.IsNullOrEmpty(m.Value.ToString) Then
                        _archive_file = m.Value.ToString.Replace("Extracting", "").Trim
                    End If
                Next
                mIdx = mIdx + 1
            Next

        End If

        Return _archive_file


    End Function

    Friend Function ParseUnRARVolumeFiles(ByVal _line As String) As String

        Dim _volume As String = String.Empty
        Dim sourcestring As String = _line

        If _line.Contains(".rar") Or _line.Contains(".part") Then

            Dim re As Regex = New Regex("^Extracting[ ]{1,2}.{1,255}\..{1,3}")
            Dim mc As MatchCollection = re.Matches(sourcestring)
            Dim mIdx As Integer = 0

            For Each m As Match In mc
                For groupIdx As Integer = 0 To m.Groups.Count - 1
                    If Not String.IsNullOrEmpty(m.Value.ToString) Then
                        _volume = m.Value.ToString.Replace("Extracting from", "").Trim
                    End If
                Next
                mIdx = mIdx + 1
            Next

        End If

        Return _volume

    End Function

    Friend Function ParseUnRarProgress(ByVal _line As String) As Integer

        Dim _percent As String = String.Empty
        Dim sourcestring As String = _line
        Dim _percent_int As Integer = -1

        Dim re As Regex = New Regex("[0-9]{1,3}%")
        Dim mc As MatchCollection = re.Matches(sourcestring)
        Dim mIdx As Integer = 0

        For Each m As Match In mc
            For groupIdx As Integer = 0 To m.Groups.Count - 1
                If Not String.IsNullOrEmpty(m.Value.ToString) Then
                    _percent = m.Value.ToString.Trim.Replace("%", "")
                    _percent_int = Integer.Parse(_percent)
                End If
            Next
            mIdx = mIdx + 1
        Next

        Return _percent_int

    End Function

    Friend Function IsUnRARPasswordValid(ByVal _filename As String, ByVal _password As String) As Boolean

        Dim _unrar_process As Process
        Dim _unrar_exe As String
        Dim _result As Boolean = False
        Dim _tmp_output As String = String.Empty

        Try

            _unrar_exe = IO.Path.Combine(Application.StartupPath, "unrar.exe")

            If IO.File.Exists(_unrar_exe) = False Then
                Throw New Exception(StringMessages.UnRARExecutableMissingException)
            End If

            _unrar_process = New Process

            With _unrar_process.StartInfo

                .CreateNoWindow = True
                .FileName = _unrar_exe
                .WorkingDirectory = Application.StartupPath
                .RedirectStandardOutput = True
                .UseShellExecute = False

                If String.IsNullOrWhiteSpace(_password) Then
                    .Arguments = String.Format("t -p- {0}", Chr(34) & _filename & Chr(34))
                Else
                    .Arguments = String.Format("t -p{0} {1}", _password, Chr(34) & _filename & Chr(34))
                End If

            End With

            _unrar_process.Start()

            _unrar_process.WaitForExit(CInt(TimeSpan.FromSeconds(5).TotalMilliseconds))

            _unrar_process.Kill()

            _tmp_output = _unrar_process.StandardOutput.ReadToEnd.ToLower

            If (_tmp_output.Contains("testing archive") And Not _tmp_output.Contains("no files to extract")) And Not String.IsNullOrWhiteSpace(_tmp_output) Then
                _result = True
            End If


        Catch ex As Exception
            _log_unrar.Error(ex, ex.Message)
        End Try

        Return _result

    End Function

    Friend Function DoUnRAR(ByVal _filename As String, ByVal _extract_dir As String, ByVal _password As String, ByVal _task_id As Guid) As DoUnRARResult

        Dim _result As New DoUnRARResult
        Dim _unrar_process As Process
        Dim _unrar_exe As String
        Dim _tmp_output As String
        Dim _out_lines As New List(Of String)

        Try

            _unrar_exe = IO.Path.Combine(Application.StartupPath, "unrar.exe")

            If IO.File.Exists(_unrar_exe) = False Then
                Throw New Exception(StringMessages.UnRARExecutableMissingException)
            End If

            _unrar_process = New Process

            With _unrar_process.StartInfo

                .CreateNoWindow = True
                .FileName = _unrar_exe
                .WorkingDirectory = Application.StartupPath
                .RedirectStandardOutput = True
                .UseShellExecute = False

                If String.IsNullOrWhiteSpace(_password) Then
                    .Arguments = String.Format("x -o+ -p- {0} {1}", Chr(34) & _filename & Chr(34), Chr(34) & _extract_dir & Chr(34))
                Else
                    .Arguments = String.Format("x -o+ -p{0} {1} {2}", _password, Chr(34) & _filename & Chr(34), Chr(34) & _extract_dir & Chr(34))
                End If

            End With

            _unrar_process.Start()

            While _unrar_process.HasExited = False

                Dim _line As String
                Dim _percent As Integer

                _line = _unrar_process.StandardOutput.ReadLine
                _out_lines.Add(_line)

                _log_unrar.Debug(_line)

                _percent = ParseUnRarProgress(_line.Trim)

                If Not _percent = -1 Then
                    _log_unrar.Debug("{0} % entpackt", _percent)
                    SetTask(_task_id, String.Format(StringMessages.UnRARTaskExtractingFilesProgress, _percent, _filename))
                End If

            End While

            _unrar_process.WaitForExit()

            For Each _line In _out_lines

                Dim _volume As String
                Dim _archive_file As String

                _log_unrar.Debug(_line)

                _archive_file = ParseUnRARArchiveFiles(_line)
                _volume = ParseUnRARVolumeFiles(_line)

                If Not String.IsNullOrWhiteSpace(_volume) Then
                    _log_unrar.Debug("RAR Volume:   {0}", _volume)
                    _result.VolumeFileName.Add(_volume)
                End If

                If Not String.IsNullOrWhiteSpace(_archive_file) Then
                    If Not _result.ArchiveFiles.ContainsKey(_archive_file) Then
                        _log_unrar.Debug("Archive File:  {0}", _archive_file)
                        _result.ArchiveFiles.Add(_archive_file, _archive_file)
                    End If
                End If

            Next

            _tmp_output = _unrar_process.StandardOutput.ReadToEnd

            If _tmp_output.Contains("All OK") Then
                _result.Success = True
            End If

            '_unrar_process.WaitForExit() --> Bullshit?

        Catch ex As Exception
            _log.Error(ex, ex.Message)
            _result.Success = False
        End Try

        Return _result


    End Function

    Friend Sub UnRAR(ByVal _taskid As Guid, ByVal _chain As UnRARChain, ByVal _sfdl_session_id As String)

        Dim _task_preCheck As Task(Of List(Of UnRARInfo))
        Dim _task_password_check As Task(Of List(Of UnRARInfo))

        Dim _rt_list As New List(Of UnRARInfo)
        Dim _files_missing As Boolean = False

        Try

            _chain.UnRARDone = True 'Sonst wird alles nochmal versucht zu entpacken

            _task_preCheck = Task.Factory.StartNew(Function() As List(Of UnRARInfo)

                                                       Try

                                                           Try

                                                               Dim _unrar As New UnRARInfo
                                                               Dim _local_file_path As String
                                                               Dim _item As New OLV_Item

                                                               _unrar.ErrorMessage = String.Empty
                                                               _unrar.ErrorOccured = False
                                                               _unrar.SFDLSession = GetSFDLSessionByKey(_sfdl_session_id)

                                                               For Each _olv_item In GetSFDLSessionByKey(_sfdl_session_id).OLVItemList.Where(Function(ByVal _myitem) _myitem.FileName.Equals(_chain.MasterUnRarChainFile.FileName))
                                                                   _item = _olv_item
                                                               Next

                                                               _local_file_path = GetDownloadFilePath(GetSettings, GetSFDLSessionByKey(_sfdl_session_id), _item)

                                                               _unrar.FileName = _local_file_path
                                                               _rt_list.Add(_unrar)

                                                           Catch ex As Exception
                                                               _log_unrar.Warn(ex, ex.Message)
                                                           End Try

                                                           If _rt_list.Count = 0 Then
                                                               Throw New NoUnRARFileFoundException(StringMessages.UnRARNoFileFoundException)
                                                           End If

                                                           If _files_missing = True Then
                                                               Throw New NoUnRARFileFoundException(StringMessages.UnRARFileMissingException)
                                                           End If

                                                       Catch ex As Exception
                                                           _rt_list.Clear()
                                                           _log_unrar.Warn(ex, ex.Message)
                                                           SetTaskComplete(_taskid, ex.Message, True)
                                                       End Try

                                                       Return _rt_list

                                                   End Function)


            If Not _task_preCheck.Result.Count = 0 Then

                SetTaskComplete(_taskid, StringMessages.UnRARExtractingFilesTaskStartMessage)

                _task_password_check = Task.Factory.StartNew(Function() As List(Of UnRARInfo)

                                                                 Dim _rt_unrar_list As New List(Of UnRARInfo)

                                                                 For Each _unrar_info In _task_preCheck.Result

                                                                     Dim _my_taskid As Guid

                                                                     _my_taskid = AddTask(String.Format(StringMessages.UnRARTaskCrackingPassword, _unrar_info.FileName))

                                                                     Try

                                                                         _unrar_info.ExtractDirectory = Path.GetDirectoryName(_unrar_info.FileName)

                                                                         If IsUnRARPasswordValid(_unrar_info.FileName, String.Empty) = True Then
                                                                             _log_unrar.Info("Es wird kein Password zum entpacken benötigt!")
                                                                             _unrar_info.PasswordRequired = False
                                                                             Throw New UnRARPasswordFoundException(StringMessages.UnRARNoPasswordNeeded)

                                                                         Else

                                                                             _unrar_info.PasswordRequired = True
                                                                             _unrar_info.PasswordFound = False

                                                                             If _settings.UnRARSettings.UseUnRARPasswordList = True Then

                                                                                 _log_unrar.Info("Suche nach passendem Passwort...")

                                                                                 For Each _pw In _settings.UnRARSettings.UnRARPasswordList

                                                                                     _log_unrar.Info("Versuche es mit Passwort {0}", _pw.ToString)

                                                                                     If IsUnRARPasswordValid(_unrar_info.FileName, _pw) Then
                                                                                         'Passwort gefunden
                                                                                         _unrar_info.Password = _pw
                                                                                         _log_unrar.Info("Wuhu - Paswort gefunden!")
                                                                                         Throw New UnRARPasswordFoundException
                                                                                     Else
                                                                                         _log_unrar.Info("Mist - das war leider nix")
                                                                                     End If

                                                                                 Next

                                                                             Else
                                                                                 _log_unrar.Info("Soll nicht nach Passwort suchen - Ok dann eben nicht")
                                                                             End If

                                                                             If _unrar_info.PasswordRequired = True And _unrar_info.PasswordFound = False Then
                                                                                 Throw New Exception(StringMessages.UnRARNoPasswordFoundException)
                                                                             End If

                                                                         End If

                                                                         _rt_unrar_list.Add(_unrar_info)

                                                                     Catch ex As NoUnRARFileFoundException
                                                                         _log_unrar.Warn("Keine Datei zum entpacken gefunden - Tschau")
                                                                         SetTaskComplete(_my_taskid, StringMessages.UnRARNoFileFoundException)

                                                                     Catch ex As UnRARPasswordFoundException
                                                                         _rt_unrar_list.Add(_unrar_info)
                                                                         _unrar_info.PasswordFound = True
                                                                         SetTaskComplete(_my_taskid, StringMessages.UnRARTaskPasswordFound)

                                                                     Catch ex As Exception
                                                                         _log_unrar.Error(ex, ex.Message)
                                                                         _unrar_info.ErrorOccured = True
                                                                         _unrar_info.ErrorMessage = ex.Message
                                                                         SetTaskComplete(_my_taskid, ex.Message, True)
                                                                     End Try

                                                                 Next

                                                                 Return _rt_unrar_list

                                                             End Function)


                Task.Factory.StartNew(Sub()

                                          For Each _unrar_info As UnRARInfo In _task_password_check.Result

                                              Dim _dorunrar_result As New DoUnRARResult
                                              Dim _my_task As Guid

                                              Try

                                                  _my_task = AddTask(String.Format(StringMessages.UnRARTaskExtractingFilesProgress, _unrar_info.FileName, 0))

                                                  _log_unrar.Info("Beginne nun zu entpacken...")

                                                  _dorunrar_result = DoUnRAR(_unrar_info.FileName, _unrar_info.ExtractDirectory, _unrar_info.Password, _my_task)

                                                  If _dorunrar_result.Success = True Then
                                                      SetTaskComplete(_my_task, StringMessages.UnRARTaskCompleted)
                                                      _log_unrar.Info("Entpacken erfolgreich abgeschlossen!")
                                                  Else
                                                      SetTaskComplete(_my_task, StringMessages.UnRARTaskCompledtedWithErrors, True)
                                                      _log_unrar.Warn("Entpacken mit Fehler abgeschlossen!")
                                                  End If

                                                  If _settings.UnRARSettings.DeleteAfterUnRAR = True And _dorunrar_result.Success = True Then

                                                      _log_unrar.Info("Lösche Archiv Dateien....")
                                                      _my_task = AddTask(StringMessages.UnRARTaskDeleteArchiveFiles)

                                                      For Each _file In _dorunrar_result.VolumeFileName

                                                          Try

                                                              If IO.File.Exists(_file) Then
                                                                  IO.File.Delete(_file)
                                                              End If

                                                          Catch ex As Exception
                                                              _log_unrar.Error(ex, "Kann Datei {0} nicht löschen!", _file)
                                                          End Try

                                                      Next

                                                      SetTaskComplete(_my_task, StringMessages.UnRARTaskDeleteArchiveFilesCompleted)
                                                      _log_unrar.Info("Archiv Dateien gelöscht!")

                                                  End If


                                              Catch ex As Exception
                                                  SetTaskComplete(_my_task, ex.Message)
                                                  _log_unrar.Error(ex, ex.Message)
                                              Finally

                                                  If Not _dorunrar_result.VolumeFileName.Count = 0 Then
                                                      ProgressPostUnRarPlugins(_dorunrar_result.ArchiveFiles.Values.ToList, _dorunrar_result.VolumeFileName, IO.Path.GetDirectoryName(_dorunrar_result.VolumeFileName(0)), _dorunrar_result.Success)
                                                  End If

                                              End Try

                                          Next

                                          _unrar_active = False
                                          _block_app_exit = False

                                      End Sub)

            Else
                _block_app_exit = False
                _unrar_active = False
            End If

        Catch ex As Exception
            _log_unrar.Error(ex, ex.Message)
        End Try

    End Sub

#End Region

#Region "Private Sub's"


    Private Sub CloseSFDLSession(sender As Object, e As EventArgs)

        Dim _toolstripitem As ToolStripItem

        _toolstripitem = CType(sender, ToolStripItem)

        RemoveSFDLSession(_toolstripitem.Tag.ToString)

    End Sub

    Private Sub RemoveSFDLSession(ByVal _sessionid As String)

        If String.IsNullOrWhiteSpace(_sessionid) = False Then

            OLV_Download_Items.RemoveObjects(GetSFDLSessionByKey(_sessionid).OLVItemList)

            RemoveSFDLSessionByKey(_sessionid)

            tss_serverinfo.DropDownItems.RemoveByKey(_sessionid)

            If tss_serverinfo.DropDownItems.Count = 0 Then
                tss_serverinfo.Visible = False
            End If

            RefreshCustomCommandPlugin(_plugin_connector)

            SyncSFDLSessionwithGUI(True)

        End If

    End Sub

    Private Sub CustomizeLoader()

        Dim _tmppath As String = String.Empty
        Dim _customize As New Customize

        Try

            If IO.File.Exists(IO.Path.Combine(Application.StartupPath, "customize.xml")) Then

                _customize = CType(_tools.XMLDeSerialize(_customize, IO.Path.Combine(Application.StartupPath, "customize.xml")), Customize)

                If Not String.IsNullOrWhiteSpace(_customize.Title) Then
                    Me.Text = "SFDL.NET 2 - " & _customize.Title
                End If

                If Not String.IsNullOrWhiteSpace(_customize.OverlayText) Then
                    OLV_Download_Items.OverlayText.Text = _customize.OverlayText
                    OLV_Download_Items.OverlayText.Alignment = _customize.OverlayTextLocation
                    OLV_Download_Items.OverlayText.TextColor = _customize.OverlayTextColor
                End If

                System.Threading.Tasks.Task.Factory.StartNew(Sub()

                                                                 If Not String.IsNullOrWhiteSpace(_customize.OverlayImage) Then

                                                                     If Not _customize.OverlayImage.StartsWith("http") Then

                                                                         _tmppath = _customize.OverlayImage.Replace("%appdir%", IO.Path.GetDirectoryName(Application.StartupPath))

                                                                     Else

                                                                         _tmppath = IO.Path.Combine(IO.Path.GetTempPath, IO.Path.GetRandomFileName)

                                                                         My.Computer.Network.DownloadFile(_customize.OverlayImage, _tmppath)

                                                                     End If

                                                                 End If

                                                             End Sub, New CancellationToken, TaskCreationOptions.PreferFairness).ContinueWith(Sub()
                                                                                                                                                  OLV_Download_Items.OverlayImage.Image = Bitmap.FromFile(_tmppath)
                                                                                                                                              End Sub, New CancellationToken, TaskContinuationOptions.NotOnFaulted, GetRootUIContext)

            End If

        Catch ex As Exception
            _log.Error(ex, "Failed to apply customization")
        End Try

    End Sub

#End Region

#Region "Main Form Events"

    Private Async Sub frm_main_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown

        Try

            Dim _load_plugin_task As Guid

            _var_sfdl_session_list = New Dictionary(Of String, SFDLSession)

            'Verzeichnisse erstellen
            If Directory.Exists(CONST_PLUGINDIR) = False Then
                Directory.CreateDirectory(CONST_PLUGINDIR)
                _log.Info("Plugin Verzeichniss erstellt!")
            End If

            Try 'Versuchen die Dateiendung .sfdl und den URI Handler zu registrieren

                Dim _file_assoiciation As New FileAssociation

                _file_assoiciation.Extension = "sfdl"
                _file_assoiciation.ContentType = "application/sfdl.net"
                _file_assoiciation.FullName = "SFDL.NET Files"
                _file_assoiciation.IconIndex = 0
                _file_assoiciation.IconPath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "Icon.ico")
                _file_assoiciation.ProperName = "SFDL.NET File"
                _file_assoiciation.AddCommand("open", Application.ExecutablePath & " " & Chr(34) & "%1" & Chr(34))

                _file_assoiciation.Create()

                _log.Info("SFDL Extension registriert!")

                If _settings.ClicknLoadEnabled Then

                    Dim _uri_handler_association As New URIHandlerAssociation

                    _uri_handler_association.RegisterSFDLURIHandler(Application.ExecutablePath)

                    _log.Info("SFDL URI Handler registriert!")

                End If

            Catch ex As Exception
                _log.Error(ex, ex.Message)
            End Try

            If _settings.PreventStandby Then

                Dim _standby_handler As New StandyHandler

                _standby_handler.PreventStandby()

                _log.Info("Standby wird nun verhindert!")

            End If

            Try

                _load_plugin_task = AddTask(StringMessages.PluginsLoadingTaskStartMessage) 'Achtung: PLugins dürfen NICHT in einem seperaten Thread geladen werden!

                _log.Info("Lade Plugins...")
                _plugin_connector.LoadPlugins(CONST_PLUGINDIR)
                _log.Info("Plugins geladen!")

                _log.Info("{0} ClicknLoad Plugin(s) geladen!", _plugin_connector.ClicknLoadPlugins.Count)
                _log.Info("{0} CustomCommand Plugin(s) geladen!", _plugin_connector.CustomCommandPlugins.Count)

                InitializePlugins(_plugin_connector)

                _log.Info("Verarbeite CommandButton Plugins...")
                ProgressCommandButtonPlugins()
                _log.Info("OK - CommandButton Plugins verarbeitet!")

                SetTaskComplete(_load_plugin_task, StringMessages.PluginsLoadingTaskCompleteMessage)

            Catch ex As Exception
                MessageBox.Show(StringMessages.PluginsLoadingGeneralErrorPrompt, StringMessages.PluginsLoadingGeneralErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                _log.Error(ex, ex.Message)
                SetTaskComplete(_load_plugin_task, "Fehler beim laden der Plugins!", True)
            End Try

            If Directory.Exists(_settings.DownloadDirectory) = False Then
                MessageBox.Show(StringMessages.DownloadDirectoryNotExistsWarningPrompt, StringMessages.DownloadDirectoryNotExistsWarningTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning)
            End If

            _log.Info("Verabeite Start Parameter und stelle Sessions wieder her...")

            Dim _list_files2open As New List(Of String)

            For Each _file In My.Application.CommandLineArgs

                Try

                    If _file.StartsWith("sfdl://") Then

                        _file = ProgressClicknLoadPlugins(_file)

                        If String.IsNullOrEmpty(_file) Then
                            Throw New PluginNotFoundException
                        End If

                        If IO.File.Exists(_file) Then
                            _list_files2open.Add(_file)
                        End If

                    Else
                        If IO.File.Exists(_file) Then
                            _list_files2open.Add(_file)
                        End If
                    End If

                Catch ex As PluginNotFoundException
                    _log.Error(ex, "Kein passendes ClicknLoad Plugin gefunden!")

                Catch ex As Exception
                    _log.Error(ex, "Konnte Startparameter nicht verarbeiten! - " & ex.Message)
                    MessageBox.Show(String.Format(StringMessages.OpenSFDLFilesGeneralErrorPrompt, ex.Message), StringMessages.OpenSFDLFilesGeneralErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error)
                End Try

            Next

            Await Task.Run(Sub() OpenSFDLHelper(_list_files2open.ToArray, True, True))

            'Wenn Windows XP -> Benutzer benachrichtigen dass nicht unterstützt
            If My.Computer.Info.OSFullName.Contains("Windows XP") Then
                MessageBox.Show(StringMessages.WindowsXPWarningPrompt, StringMessages.WindowsXPWarningTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            End If

            If _settings.SearchUpdates = True Then
                'Nach neuer Version suchen
                bgw_update_checker.RunWorkerAsync()
            End If

            If _tools.isAdministrator = False Then 'Benachritung nur nötig wenn SFDL.NET nicht als admin ausgeführt wird

                If IO.File.Exists(Path.Combine(Application.StartupPath, ".installstate")) Then

                    Dim _installstate_path As String

                    _installstate_path = My.Computer.FileSystem.ReadAllText(Path.Combine(Application.StartupPath, ".installstate")).Trim

                    If _installstate_path.Equals(Path.Combine(Application.StartupPath).ToString) = False Then

                        If MessageBox.Show(StringMessages.InstallPathChangedPrompt, StringMessages.InstallPathChangedTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
                            RunAsAdmin()
                        End If

                    End If

                Else
                    If MessageBox.Show(StringMessages.InstallPathChangedPrompt, StringMessages.InstallPathChangedTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
                        RunAsAdmin()
                    End If
                End If

            Else
                _log.Info("SFDL.NET 2 wird als Administrator ausgeführt!")
                UpdateInstallState()
            End If

        Catch ex As UserCancelException

            'Benutzer hat abgebrochen

        Catch ex As Exception

            MessageBox.Show(String.Format(StringMessages.GeneralErrorPrompt, ex.Message), StringMessages.GeneralErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error)
            _log.Error(ex, ex.Message)

        End Try


    End Sub

    Private Sub frm_main_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing

        'Aktuell geöffnete SFDL File wegschreiben damit der Zustand beim nächsten Start wiederhergestellt werden kann
        Try

            If _var_download_running = True Then

                If MessageBox.Show(StringMessages.AppClosingDownloadStillRunningWarningPropmpt, StringMessages.AppClosingDownloadStillRunningWarningTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.No Then
                    e.Cancel = True
                End If

            End If

            If _unrar_active = True Then

                If MessageBox.Show(StringMessages.AppClosingUnRARStillRunningWarningPropmpt, StringMessages.AppClosingUnRARStillRunningWarningTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.No Then
                    e.Cancel = True
                End If

            End If

            _log.Info("Speichere geöffnete SFDL Sessions..")

            For Each _session In _var_sfdl_session_list

                Dim _saved_checked_item As New List(Of OLV_Item)

                _saved_checked_item.AddRange(_session.Value.OLVItemList.Where(Function(_my_item As OLV_Item) _my_item.Checked = True))

                _session.Value.SavedCheckedItems = _saved_checked_item

                _tools.XMLSerialize(_session.Value, Path.Combine(Path.Combine(Environment.GetEnvironmentVariable("appdata"), "SFDL.NET 2"), Path.GetRandomFileName & ".restore"))

            Next

            _log.Info("SFDL Sessions gespeichert!")
            _log.Info("Verstecke Restore Files...")

            For Each _file In Directory.GetFiles(Path.GetDirectoryName(Application.ExecutablePath), "*.restore", SearchOption.TopDirectoryOnly)

                Dim _file_info As New FileInfo(_file)
                _file_info.Attributes = FileAttributes.Hidden

            Next

            NativeMethods.FreeConsole()
            Console.WriteLine("")

            My.Settings.UserWindowSize = Me.Size
            My.Settings.UserWindowState = Me.WindowState
            My.Settings.Save()

            _log.Info("Abgeschlossen")

        Catch ex As Exception
            _log.Error(ex, ex.Message)
        End Try

    End Sub

    Private Sub frm_main_Load(sender As Object, e As EventArgs) Handles MyBase.Load


        _ui_context = TaskScheduler.FromCurrentSynchronizationContext 'Für UI Zugriff

        olvc_status.ImageGetter = New ImageGetterDelegate(AddressOf ImageUpdateEventImageGetter) ' Status IMages


        If My.Settings.UserWindowSize.IsEmpty = False Then
            Me.Size = My.Settings.UserWindowSize
        End If

        Me.WindowState = My.Settings.UserWindowState

        'Customize laden
        CustomizeLoader()

        'WebSocket Starten

        WSSHelper.ProgressRemoteControlState(_settings.RemoteControlSettings)

        _taskbar_manager = TaskbarManager.Instance


        Try
            NativeMethods.AttachConsole(-1)
        Catch ex As Exception
            _log.Error(ex, "Failed to attach Console")
        End Try

    End Sub

    Private Sub frm_main_Resize(sender As Object, e As EventArgs) Handles MyBase.Resize

        Try

            If Not _settings Is Nothing Then

                If _settings.Send2Tray = True And Me.WindowState = FormWindowState.Minimized Then

                    If Me.WindowState = FormWindowState.Minimized Then
                        Me.WindowState = FormWindowState.Minimized
                        NotifyIcon.Visible = True
                        Me.Hide()

                    End If

                End If

            End If

        Catch ex As Exception
            _log.Error(ex, ex.Message)
        End Try

    End Sub

    Private Sub MainPanel_Resize(sender As Object, e As EventArgs) Handles MainPanel.Resize
        OLV_Download_Items.Size = MainPanel.Size
    End Sub

#End Region

#Region "Main Form Button Events & Co."


    Private Sub cmd_instantvideo_Click(sender As Object, e As EventArgs) Handles cmd_instantvideo.Click

        Try

            Dim _instant_video_list As New List(Of OLV_Item)
            Dim _exec_vlc As String = String.Empty

            If CheckIfVLCInstalled() = False Then
                Throw New Exception("Der VLC PLayer ist auf deinem System nicht installiert. Bitte installiere den VLC Player um Instant Video zu nutzen!")
            End If

            For Each _session In GetSFDLSessionList

                Dim _var_sfdl_session As SFDLSession = _session.Value

                If _var_sfdl_session.SessionState = SFDLSessionEnums.SFDLSessionState.DownloadRunning Then

                    For Each _chain In _var_sfdl_session.UnRarChains

                        If _chain.ReadyForInstantVideo = True Then
                            _instant_video_list.Add(_chain.MasterUnRarChainFile)
                        End If

                    Next

                End If


            Next


            If _instant_video_list.Count = 0 Then
                Throw New Exception("Keine SFDL Session mit Instand Video verfügbar!")
            End If

            frm_choose_instant_video.VideoList = _instant_video_list

            frm_choose_instant_video.ShowDialog()


        Catch ex As Exception
            _log.Error(ex, ex.Message)
            MessageBox.Show(ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

    Private Sub LogAnzeigenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles LogAnzeigenToolStripMenuItem.Click

        Dim _log_helper As New LogHelper

        MessageBox.Show("Achtung! Das Anzeigen des Logs ist noch in der Testphase!", "Achtung", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)

        _log_helper.AddGUILogTarget()

    End Sub

    Private Async Sub tbl_start_download_Click(sender As Object, e As EventArgs) Handles tbl_start_download.Click

        Try

            If _var_sfdl_session_list.Count = 0 Then
                Throw New Exception(StringMessages.StartDownloadErrorNoSFDLFileLoaded)
            End If

            If Directory.Exists(_settings.DownloadDirectory) = False Then
                Throw New FileNotFoundException(StringMessages.StartDownloadErrorDownloadDirectoryNotFound)
            End If

            If IO.File.Exists(IO.Path.Combine(Application.StartupPath, "unrar.exe")) = False Then

                If MessageBox.Show(StringMessages.StartDownloadWarningUnRARMissingPrompt, StringMessages.StartDownloadWarningUnRARMissingTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) = Windows.Forms.DialogResult.No Then
                    Throw New FileNotFoundException(StringMessages.StartDownloadErrorUnRARMissingUserCancel)
                End If

            End If

            ClearSizeSpeedCollection()

            _log.Info("Bereite GUI für Startenden Download vor...")

            'Lock Controls
            tbl_start_download.Enabled = False
            tbl_stop_download.Enabled = True

            _var_download_running = True
            _var_download_stop_in_progress = False

            cmd_instantvideo.Enabled = False

            tss_status.Text = "Downloading..."
            tss_status.Image = My.Resources.download


            Await Task.Run(Sub()

                               For Each _session In _var_sfdl_session_list

                                   _session.Value.ActiveThreads = 0

                                   For Each _olv_item In _session.Value.OLVItemList

                                       If _olv_item.Checked = True Then
                                           _olv_item.Status = Status.Waiting
                                           _olv_item.StatusText = StringMessages.OLVItemStatusWaiting
                                       Else

                                           If Not _olv_item.Status = Status.AlreadyDownloaded Then

                                               _olv_item.Status = Status.NotSelected
                                               _olv_item.StatusText = String.Empty

                                           End If


                                       End If

                                       _olv_item.DownloadSpeed = String.Empty
                                       _olv_item.Progress = 0
                                       _olv_item.SizeDownloaded = 0

                                       UpdateItemSizeSpeedCollection(_olv_item)

                                   Next

                                   _session.Value.SessionState = SFDLSessionEnums.SFDLSessionState.Queued

                               Next


                               _log.Info("OK - GUI vorbereitet")
                               _log.Info("Starte Download ThreadHandler....")


                               RemoveHandler ThreadHandler.FileDownloadComplete, AddressOf FileDownloadCompleteEvent
                               RemoveHandler ThreadHandler.DownloadCompleted, AddressOf DownloadCompleteEvent
                               AddHandler ThreadHandler.DownloadCompleted, AddressOf DownloadCompleteEvent
                               AddHandler ThreadHandler.FileDownloadComplete, AddressOf FileDownloadCompleteEvent

                               _thread_handler.HandleThreads()
                               _log.Info("OK - Thread Handler gestartet")

                           End Sub)

            If TaskbarManager.IsPlatformSupported Then
                _taskbar_manager.SetProgressValue(0, 100)
                _taskbar_manager.SetProgressState(TaskbarProgressBarState.Indeterminate)
            End If


        Catch ex As Exception

            _log.Error(ex, ex.Message)

            MessageBox.Show(String.Format(StringMessages.StartDownloadGeneralErrorPrompt, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning)

            tbl_start_download.Enabled = True
            tbl_stop_download.Enabled = False
            tss_status.Text = StringMessages.StartDownloadGeneralErrorStatusMessage

            If TaskbarManager.IsPlatformSupported Then
                _taskbar_manager.SetProgressState(TaskbarProgressBarState.Error)
            End If

        End Try

    End Sub

    Private Async Sub tbl_stop_download_Click(sender As Object, e As EventArgs) Handles tbl_stop_download.Click

        Try

            _log.Info("Starte 'Stop Download' Thread....")

            _var_download_stop_in_progress = True

            Await Task.Run(Sub()

                               RemoveHandler ThreadHandler.StopDownloadComplete, AddressOf StopDownloadCompleteEvent
                               AddHandler ThreadHandler.StopDownloadComplete, AddressOf StopDownloadCompleteEvent

                               _thread_handler.StopThreads()

                               _log.Info("OK - Thread gestartet")

                           End Sub)

            If TaskbarManager.IsPlatformSupported Then
                _taskbar_manager.SetProgressState(TaskbarProgressBarState.Paused)
            End If

        Catch ex As Exception
            _log.Error(ex, ex.Message)
            MessageBox.Show(StringMessages.StopDownloadGeneralErrorPrompt, StringMessages.StopDownloadGeneralErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

    Private Async Sub ÖffnenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ÖffnenToolStripMenuItem.Click

        Try

            If Not OFD_SFDL.ShowDialog = DialogResult.Cancel Then
                Await Task.Run(Sub() OpenSFDLHelper(OFD_SFDL.FileNames))
            End If

        Catch ex As UserCancelException
            'Benutzer hat abgebrochen

        Catch ex As Exception
            _log.Error(ex, ex.Message)
            MessageBox.Show(String.Format(StringMessages.OpenSFDLFilesGeneralErrorPrompt, ex.Message), StringMessages.OpenSFDLFilesGeneralErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

    Private Sub EinstellungenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles EinstellungenToolStripMenuItem.Click

        Try

            AddHandler frm_settings.SettingsUpdated, AddressOf frm_setting_settings_update_event

            frm_settings.ShowDialog()

            RemoveHandler frm_settings.SettingsUpdated, AddressOf frm_setting_settings_update_event

        Catch ex As Exception
            _log.Error(ex, ex.Message)
            MessageBox.Show(StringMessages.SettingsSaveGeneralErrorPrompt, StringMessages.SettingsSaveGeneralErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

    Private Sub BeendenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BeendenToolStripMenuItem.Click

        Dim _block As Boolean = False

        If _var_download_running = True Then

            If MessageBox.Show(StringMessages.AppClosingDownloadStillRunningWarningPropmpt, StringMessages.AppClosingDownloadStillRunningWarningTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.No Then
                _block = True
            End If

        End If

        If _unrar_active = True Then

            If MessageBox.Show(StringMessages.AppClosingUnRARStillRunningWarningPropmpt, StringMessages.AppClosingUnRARStillRunningWarningTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.No Then
                _block = True
            End If

        End If

        If _block_app_exit = True Then

            If MessageBox.Show(StringMessages.AppClosingGenericJobStillRunningWarningPropmpt, StringMessages.AppClosingGenericJobStillRunningWarningTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.No Then
                _block = True
            End If

        End If

        If _block = False Then
            Application.Exit()
        End If

    End Sub

    Private Sub AlleFertigenDownloadsEntfernenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AlleFertigenDownloadsEntfernenToolStripMenuItem.Click


        If MessageBox.Show(StringMessages.RemoveAllCompletedDownloadsPrompt, StringMessages.RemoveAllCompletedDownloadsPrompTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then

            Task.Factory.StartNew(Sub()

                                      For Each _group In OLV_Download_Items.OLVGroups

                                          If GetSFDLSessionByKey(_group.Name).SessionState = SFDLSessionEnums.SFDLSessionState.DownloadComplete Then

                                              OLV_Download_Items.RemoveObjects(GetSFDLSessionByKey(_group.Name).OLVItemList)

                                              tss_serverinfo.DropDownItems.RemoveByKey(_group.Name)
                                              RemoveSFDLSessionByKey(_group.Name)

                                          End If

                                      Next

                                      If tss_serverinfo.DropDownItems.Count = 0 Then
                                          tss_serverinfo.Visible = False
                                      End If

                                      SyncSFDLSessionwithGUI(True)

                                  End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext)

        End If

    End Sub

    Private Sub AlleDownloadsEntfernenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AlleDownloadsEntfernenToolStripMenuItem.Click

        Try


            If GetDownloadRunning = True Then
                Throw New Exception(StringMessages.RemoveAllDownloadsDownloadStillRunningException)
            End If

            If MessageBox.Show(StringMessages.RemoveAllDownloadsPrompt, StringMessages.RemoveAllDownloadsPromptTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then

                Task.Run(Sub()

                             _var_sfdl_session_list.Clear()
                             OLV_Download_Items.ClearObjects()

                             RefreshCustomCommandPlugin(_plugin_connector)

                         End Sub)

                tss_serverinfo.DropDownItems.Clear()
                tss_serverinfo.Visible = False

                SyncSFDLSessionwithGUI(True)

            End If

        Catch ex As Exception
            _log.Error(ex, ex.Message)
            MessageBox.Show(ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try


    End Sub

    Private Sub PluginManagerToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles PluginManagerToolStripMenuItem.Click
        frm_pluginmanager.ShowDialog()
        frm_pluginmanager.Dispose()
    End Sub

    Private Sub AllesMakierenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AllesMakierenToolStripMenuItem.Click

        Task.Factory.StartNew(Sub()

                                  Try

                                      For Each _session In _var_sfdl_session_list
                                          OLV_Download_Items.CheckObjects(_session.Value.OLVItemList)
                                      Next

                                  Catch ex As Exception
                                      _log.Error(ex, ex.Message)
                                  End Try

                              End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext)

    End Sub

    Private Sub AllesDeToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AllesDeToolStripMenuItem.Click

        Task.Factory.StartNew(Sub()
                                  Try
                                      For Each _session In _var_sfdl_session_list
                                          OLV_Download_Items.UncheckObjects(_session.Value.OLVItemList)
                                      Next
                                  Catch ex As Exception
                                      _log.Error(ex, ex.Message)
                                  End Try
                              End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext)

    End Sub

    Private Sub ÜberSFDLNET2ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ÜberSFDLNET2ToolStripMenuItem.Click
        AboutBox.ShowDialog()
    End Sub

    Private Sub SFDLNET2AlsAdministratorAusführenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SFDLNET2AlsAdministratorAusführenToolStripMenuItem.Click

        RunAsAdmin()

    End Sub

    Private Sub EinstellungenZurücksetztenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles EinstellungenZurücksetztenToolStripMenuItem.Click

        If MessageBox.Show(StringMessages.ResetSettingsQuestionPrompt, StringMessages.ResetSettingsQuestionTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then

            Try

                IO.Directory.Delete(Path.Combine(Environment.GetEnvironmentVariable("appdata"), "SFDL.NET 2"), True)

            Catch ex As Exception
                MessageBox.Show("Einstellungen konnten nicht zurückgesetzt werden!")
            End Try

            MessageBox.Show(StringMessages.ResetSettingsSuccessPrompt, StringMessages.ResetSettingsSuccessTitle, MessageBoxButtons.OK, MessageBoxIcon.Information)

        End If

    End Sub

#End Region

#Region "Notify Icon"

    Private Sub MaximierenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles MaximierenToolStripMenuItem.Click

        OLV_Download_Items.Visible = True
        Me.Show()
        Me.WindowState = FormWindowState.Normal
        NotifyIcon.Visible = False

    End Sub

    Private Sub DownloadInfoToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DownloadInfoToolStripMenuItem.Click

        Dim _string_info As New StringBuilder

        If _var_download_running = False Then
            _string_info.AppendLine("Kein Download aktiv!")
        Else
            _string_info.AppendLine("")
            _string_info.AppendLine(String.Format(StringMessages.NotifyIconBaloonStatusMessageSpeed, _var_download_speed))
            _string_info.AppendLine(String.Format(StringMessages.NotifyIconBaloonStatusMessageProgress, _var_download_progress))
            _string_info.AppendLine(String.Format(StringMessages.NotifyIconBaloonStatusMessageETA, _var_remaining_time))
        End If


        NotifyIcon.BalloonTipIcon = ToolTipIcon.Info
        NotifyIcon.BalloonTipTitle = StringMessages.NotifyIconBaloonStatusTitle
        NotifyIcon.BalloonTipText = _string_info.ToString
        NotifyIcon.ShowBalloonTip(3000)


    End Sub


    Private Sub NotifyIcon_DoubleClick(sender As Object, e As EventArgs) Handles NotifyIcon.DoubleClick

        Try

            Me.Show()
            Me.WindowState = FormWindowState.Normal
            NotifyIcon.Visible = False

        Catch ex As Exception
            _log.Error(ex, ex.Message)
        End Try

    End Sub



#End Region

#Region "Friend Funktionen und Subs"

    Protected Friend Sub SetTask(ByVal _taskid As Guid, ByVal _status_text As String)

        Task.Factory.StartNew(Sub()

                                  Try

                                      Monitor.Enter(_obj_lock_Task)

                                      Dim _olv_task_item As New OLV_Task_Item

                                      For Each _olv_task As OLV_Task_Item In OLV_Task_List.Objects

                                          If _olv_task.TaskID.Equals(_taskid) Then
                                              _olv_task_item = _olv_task
                                          End If

                                      Next

                                      _olv_task_item.StatusText = _status_text

                                      OLV_Task_List.RefreshObject(_olv_task_item)

                                  Catch ex As Exception
                                      _log.Error(ex, ex.Message)

                                  Finally
                                      Monitor.Exit(_obj_lock_Task)
                                  End Try

                              End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext)

    End Sub

    Protected Friend Function AddTask(ByVal _taskname As String) As Guid

        Dim _rt As Guid

        Task.Factory.StartNew(Sub()

                                  Try

                                      Monitor.Enter(_obj_lock_Task)

                                      Dim _olv_task As New OLV_Task_Item

                                      MainTableLayout.RowStyles(1).SizeType = SizeType.Percent
                                      MainTableLayout.RowStyles(1).Height = 20


                                      OLV_Task_List.Visible = True

                                      _olv_task.TaskID = Guid.NewGuid
                                      _olv_task.StatusText = _taskname
                                      _olv_task.Progress = 0

                                      OLV_Task_List.AddObject(_olv_task)

                                      _rt = _olv_task.TaskID

                                  Catch ex As Exception
                                      _log.Error(ex, ex.Message)

                                  Finally
                                      Monitor.Exit(_obj_lock_Task)
                                  End Try

                              End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext).Wait()

        Return _rt

    End Function

    Protected Friend Sub SetTaskComplete(ByVal _taskid As Guid, ByVal _status_text As String, Optional ByVal _error As Boolean = False)

        Task.Factory.StartNew(Sub()

                                  Try

                                      Monitor.Enter(_obj_lock_Task)

                                      Dim _olv_task_item As New OLV_Task_Item

                                      For Each _olv_task As OLV_Task_Item In OLV_Task_List.Objects

                                          If _olv_task.TaskID.Equals(_taskid) Then
                                              _olv_task_item = _olv_task
                                          End If

                                      Next

                                      _olv_task_item.StatusText = _status_text

                                      If _error = True Then
                                          _olv_task_item.Progress = 2
                                      Else
                                          _olv_task_item.Progress = 1
                                      End If

                                      OLV_Task_List.RefreshObject(_olv_task_item)

                                  Catch ex As Exception
                                      _log.Error(ex, ex.Message)

                                  Finally
                                      Monitor.Exit(_obj_lock_Task)
                                  End Try

                              End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext).ContinueWith(Sub()

                                                                                                                           Task.Delay(5000).ContinueWith(Sub()
                                                                                                                                                             TaskCleanup(_taskid)
                                                                                                                                   End Sub, New CancellationToken, TaskContinuationOptions.AttachedToParent, GetRootUIContext)

                                                                                                                       End Sub)

    End Sub

    Private Sub TaskCleanup(ByVal _state As Object)

        Try

            Monitor.Enter(_obj_lock_Task)

            Dim _taskid As Guid
            Dim _items_to_remove As New List(Of OLV_Task_Item)

            _taskid = CType(_state, Guid)

            For Each _item As OLV_Task_Item In OLV_Task_List.Objects
                If _item.TaskID.Equals(_taskid) Then
                    _items_to_remove.Add(_item)
                End If
            Next


            OLV_Task_List.RemoveObjects(_items_to_remove)

        Catch ex As Exception

        Finally

            If OLV_Task_List.GetItemCount = 0 Then

                OLV_Task_List.ClearObjects()
                OLV_Task_List.Hide()
                MainTableLayout.RowStyles(1).SizeType = SizeType.Percent
                MainTableLayout.RowStyles(1).Height = 0
                MainTableLayout.RowStyles(0).Height = 100
                MainTableLayout.RowStyles(0).SizeType = SizeType.Percent

            End If

            Monitor.Exit(_obj_lock_Task)

        End Try

    End Sub

#End Region

#Region "Update Check"

    Private Sub bgw_update_checker_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgw_update_checker.DoWork

        Dim _update_check As New UpdateChecker

        If _update_check.NewUpdateAvailible = True Then
            bgw_update_checker.ReportProgress(1)
        End If

    End Sub

    Private Sub bgw_update_checker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bgw_update_checker.ProgressChanged

        'Benutzer benachrichtigen
        If e.ProgressPercentage = 1 Then
            frm_new_update.ShowDialog()
        End If

    End Sub

#End Region

#Region "Toolstrip Button Events"

    Private Sub BearbeitenToolStripMenuItem_DropDownOpening(sender As Object, e As EventArgs) Handles BearbeitenToolStripMenuItem.DropDownOpening

        SFDLDateiSchließenToolStripMenuItem_overview.DropDownItems.Clear()

        For Each _sfdlsession As SFDLSession In GetSDFLSessionList.Values

            Dim _newtoolstripitem As ToolStripItem

            _newtoolstripitem = SFDLDateiSchließenToolStripMenuItem_overview.DropDownItems.Add(String.Format("{0}", _sfdlsession.SFDLFile.Description), My.Resources.Icon.ToBitmap)
            _newtoolstripitem.Tag = _sfdlsession.SFDLSessionName

            AddHandler _newtoolstripitem.Click, AddressOf CloseSFDLSession

        Next

        If SFDLDateiSchließenToolStripMenuItem_overview.DropDownItems.Count = 0 Then
            SFDLDateiSchließenToolStripMenuItem_overview.Enabled = False
        Else
            SFDLDateiSchließenToolStripMenuItem_overview.Enabled = True
        End If

    End Sub

#End Region

#Region "Context Menu Events"

    Private Sub CMS_OLV_Download_Opening(sender As Object, e As CancelEventArgs) Handles CMS_OLV_Download.Opening

        If GetSFDLSessionList.Values.Count = 0 Then

            CMS_AlleDateienImDiesemPaketMakierenToolStripMenuItem.Enabled = False
            CMS_BeinhaltendenOrdnerÖfnnenToolStripMenuItem.Enabled = False
            CMS_SFDLDateiSchließenToolStripMenuItem.Enabled = False
            CMS_AlleDateienImDiesemPaketDemakierenToolStripMenuItem.Enabled = False

        Else

            CMS_AlleDateienImDiesemPaketMakierenToolStripMenuItem.Enabled = True
            CMS_BeinhaltendenOrdnerÖfnnenToolStripMenuItem.Enabled = True
            CMS_SFDLDateiSchließenToolStripMenuItem.Enabled = True
            CMS_AlleDateienImDiesemPaketDemakierenToolStripMenuItem.Enabled = True


        End If

    End Sub

    Private Sub SFDLDateiSchließenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles CMS_SFDLDateiSchließenToolStripMenuItem.Click

        If Not OLV_Download_Items.SelectedObjects.Count = 0 Then

            Dim _selected_olv_item As New OLV_Item

            _selected_olv_item = CType(OLV_Download_Items.SelectedObject, OLV_Item)

            RemoveSFDLSession(_selected_olv_item.SFDLSessionName)

        End If

    End Sub

    Private Sub AlleDateienImDiesemPaketMakierenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles CMS_AlleDateienImDiesemPaketMakierenToolStripMenuItem.Click

        Task.Factory.StartNew(Sub()

                                  If Not OLV_Download_Items.SelectedObjects.Count = 0 Then

                                      Dim _selected_olv_item As New OLV_Item

                                      _selected_olv_item = CType(OLV_Download_Items.SelectedObjects(0), OLV_Item)

                                      If GetSFDLSessionByKey(_selected_olv_item.SFDLSessionName).OLVItemList.Where(Function(_my_item As OLV_Item) ((_my_item.Status = Status.Complete Or _my_item.Status = Status.CompleteHashValid) Or _my_item.Status = Status.AlreadyDownloaded) And _my_item.PackageName.Equals(_selected_olv_item.PackageName)).Count > 0 Then

                                          If MessageBox.Show(StringMessages.MarkAllDownloadPackageItemsExistingFilesQuestionPrompt, StringMessages.MarkAllDownloadPackageItemsExistingFilesQuestionTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then

                                              For Each _myitem In GetSFDLSessionByKey(_selected_olv_item.SFDLSessionName).OLVItemList

                                                  If _myitem.PackageName.EndsWith(_selected_olv_item.PackageName) Then
                                                      OLV_Download_Items.CheckObject(_myitem)
                                                  End If

                                              Next

                                          Else

                                              For Each _myitem In GetSFDLSessionByKey(_selected_olv_item.SFDLSessionName).OLVItemList

                                                  If _myitem.PackageName.Equals(_selected_olv_item.PackageName) Then

                                                      If (_myitem.Status = Status.Complete Or _myitem.Status = Status.CompleteHashValid) Or _myitem.Status = Status.AlreadyDownloaded Then
                                                          'do nothing
                                                      Else
                                                          OLV_Download_Items.CheckObject(_myitem)
                                                      End If

                                                  End If

                                              Next

                                          End If

                                      Else

                                          For Each _myitem In GetSFDLSessionByKey(_selected_olv_item.SFDLSessionName).OLVItemList
                                              If _myitem.PackageName.EndsWith(_selected_olv_item.PackageName) Then
                                                  OLV_Download_Items.CheckObject(_myitem)
                                              End If
                                          Next

                                      End If

                                  End If

                              End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext)

    End Sub

    Private Sub AlleDateienImDiesemPaketDemakierenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles CMS_AlleDateienImDiesemPaketDemakierenToolStripMenuItem.Click

        Task.Factory.StartNew(Sub()

                                  If Not OLV_Download_Items.SelectedObjects.Count = 0 Then

                                      Dim _selected_olv_item As New OLV_Item

                                      _selected_olv_item = CType(OLV_Download_Items.SelectedObjects(0), OLV_Item)

                                      For Each _myitem In GetSFDLSessionByKey(_selected_olv_item.SFDLSessionName).OLVItemList
                                          If _myitem.PackageName.EndsWith(_selected_olv_item.PackageName) Then
                                              OLV_Download_Items.UncheckObject(_myitem)
                                          End If
                                      Next

                                  End If

                              End Sub, New CancellationToken, TaskCreationOptions.None, GetRootUIContext)

    End Sub

    Private Sub BeinhaltendenOrdnerÖfnnenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles CMS_BeinhaltendenOrdnerÖfnnenToolStripMenuItem.Click

        Try

            If Not OLV_Download_Items.SelectedObjects.Count = 0 Then

                Dim _selected_olv_item As New OLV_Item
                Dim _dl_path As String = String.Empty

                _selected_olv_item = CType(OLV_Download_Items.SelectedObjects(0), OLV_Item)

                _dl_path = GetDownloadFilePath(_settings, GetSFDLSessionByKey(_selected_olv_item.SFDLSessionName), _selected_olv_item)

                _tools.OpenExplorer(Path.GetDirectoryName(_dl_path))

            End If

        Catch ex As Exception
            _log.Error(ex, ex.Message)
            MessageBox.Show(StringMessages.DownloadItemCMOpenContainingFolderErrorPrompt, StringMessages.DownloadItemCMOpenContainingFolderErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning)
        End Try

    End Sub

#End Region

#Region "DragnDrop"

    Private Sub OLV_Download_Items_DragEnter(sender As Object, e As DragEventArgs) Handles OLV_Download_Items.DragEnter

        If e.Data.GetDataPresent(DataFormats.FileDrop) Then
            e.Effect = DragDropEffects.Copy
        End If

    End Sub

    Private Sub OLV_Download_Items_DragDrop(sender As Object, e As DragEventArgs) Handles OLV_Download_Items.DragDrop

        Dim _files() As String

        Try

            _files = CType(e.Data.GetData(DataFormats.FileDrop), String())

            If Not _files Is Nothing Then

                Dim _files2Open As New List(Of String)

                If Not _files.Length = 0 Then

                    _files2Open.AddRange(From _dragdropfile In _files Where Path.GetExtension(_dragdropfile).ToLower = ".sfdl")

                    OpenSFDLHelper(_files2Open.ToArray)

                End If

            End If

        Catch ex As UserCancelException
            _log.Info(ex, "Abbruch durch Benutzer!")

        Catch ex As Exception
            _log.Error(ex, ex.Message)
            MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

#End Region

#Region "Post Download"

    Private Sub SFDLLoaderSchließenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SFDLLoaderSchließenToolStripMenuItem.Click

        If SFDLLoaderSchließenToolStripMenuItem.Checked = True Then
            _post_dl_exit_app = True
        Else
            _post_dl_exit_app = False
        End If

    End Sub

    Private Sub PCHerunterfahrenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles PCHerunterfahrenToolStripMenuItem.Click

        If PCHerunterfahrenToolStripMenuItem.Checked = True Then
            _post_dl_shutdown_computer = True
        Else
            _post_dl_shutdown_computer = False
        End If

    End Sub

    Private Sub PostDLAction_ExitApp()
        Me.Close()
    End Sub

    Private Sub PostDLAction_ShutdownComputer()
        Shell("shutdown -s -t 60", AppWinStyle.Hide, True)
        Me.Close()
    End Sub

#End Region

#Region "Speed Limit"

    Private Sub txt_maxspeed_KeyDown(sender As Object, e As KeyEventArgs) Handles txt_maxspeed.KeyDown

        If (e.KeyCode = Keys.Enter Or e.KeyCode = Keys.Return) Then
            cmd_set_and_clear_maxspeed.PerformClick()
        End If

    End Sub

    Private Sub txt_maxspeed_TextChanged(sender As Object, e As EventArgs) Handles txt_maxspeed.TextChanged
        txt_maxspeed.BackColor = Color.White
    End Sub

    Private Sub cmd_set_and_clear_maxspeed_Click(sender As Object, e As EventArgs) Handles cmd_set_and_clear_maxspeed.Click

        Dim _string_maxspeed As String = txt_maxspeed.Text

        Try

            If String.IsNullOrEmpty(_string_maxspeed) Then
                _thread_handler.MaxDownloadSpeed = 0
            Else

                If IsNumeric(_string_maxspeed) Then
                    _thread_handler.MaxDownloadSpeed = CInt(_string_maxspeed)
                    txt_maxspeed.BackColor = Color.GreenYellow
                Else
                    txt_maxspeed.Text = String.Empty
                    txt_maxspeed.ToolTipText = String.Format("Du musst einen Zahl von 1 - {0} eingeben", Integer.MaxValue)
                End If

            End If

        Catch ex As Exception

        End Try

    End Sub


#End Region

End Class